﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace WJP.Reflection
{
    /// <summary>
    /// 方法缓存
    /// </summary>
    internal class MethodCacheKey
    {
        internal Type Type;
        internal string MethodName;
        internal Type[] ParamTypes;
        private int _hashKey;

        public MethodCacheKey(MethodInfo methodInfo)
        {
            this.Type = methodInfo.DeclaringType;
            this.MethodName = methodInfo.Name;
            ParameterInfo[] parameters = methodInfo.GetParameters();
            this.ParamTypes = new Type[parameters.Length];
            this._hashKey = this.Type.GetHashCode();
            this._hashKey ^= this.MethodName.GetHashCode();
            int i = 0;
            int num = parameters.Length;
            while (i < num)
            {
                Type parameterType = parameters[i].ParameterType;
                this._hashKey ^= parameterType.GetHashCode();
                this.ParamTypes[i] = parameterType;
                i++;
            }
        }

        public MethodCacheKey(Type type, string methodName, Type[] paramTypes)
        {
            this.Type = type;
            this.MethodName = methodName;
            this.ParamTypes = paramTypes;
            this._hashKey = type.GetHashCode();
            this._hashKey ^= methodName.GetHashCode();
            int i = 0;
            int num = paramTypes.Length;
            while (i < num)
            {
                Type type2 = paramTypes[i];
                this._hashKey ^= type2.GetHashCode();
                i++;
            }
        }

        public override bool Equals(object obj)
        {
            MethodCacheKey methodCacheKey = obj as MethodCacheKey;
            return methodCacheKey != null && methodCacheKey.Type == this.Type && methodCacheKey.MethodName == this.MethodName && this.ArrayEquals(methodCacheKey.ParamTypes, this.ParamTypes);
        }

        private bool ArrayEquals(Type[] a1, Type[] a2)
        {
            if (a1.Length != a2.Length)
                return false;
            
            for (int i = 0; i < a1.Length; i++)
            {
                if (a1[i] != a2[i])
                    return false;
            }
            return true;
        }

        public override int GetHashCode()
        {
            return this._hashKey;
        }
    }
}
